﻿#define _CRT_SECURE_NO_WARNINGS
//--------------------------------库函数
# include <stdio.h>
//# include <math.h>
//int main()
//{
//	double a = 16.0;
//	double b = sqrt(a);
//	printf("%lf\n", b);
//	return 0;
//}
//------------------------------------- ⾃定义函数
//int add(int x, int y)//形式参数
//{
//	return x + y;
//}
//int main()
//{
//	int a = 0;
//	int b = 0;
//	scanf("%d %d", &a, &b);
//	///函数Add被使用的场景 - 函数的调用,//调⽤加法函数，完成a和b的相加
//	int c = add(a, b);//实参--函数调用
//	printf("%d",c);
//
//	return 0;
//}
//// ------//写一个函数，在屏幕上打印hehe
//void print()//返回类型是void，就表示函数不返回任何值
////--参数部分的void表示这个函数不接受参数
//{
//	printf("hehe\n");
//}
//int main()
//{
//	print();
//	return 0;
//}
//--------------------------------- 形参和实参
//函数的定义
//int Add(int x, int y)//形参
//{
//    int z = 0;
//    z = x + y;
//    return z;
//}
//int main()
//{
//    int a = 0;
//    int b = 0;
//    //输入
//    scanf("%d %d", &a, &b);
//    //调用加法函数，完成a和b的相加
//    //求和的结果放在r中
//    int r = Add(a, b); //函数的调用//实参
//    //输出
//    printf("%d\n", r);
//    return 0;
//}
//----------------------------- return 语句
//--return后边可以是⼀个数值，也可以是⼀个表达式，如果是表达式则先执⾏表达式，再返回表达式
//的结果。
//int Add(int x, int y)
//{
//    return x + y;
//}
//----return后边也可以什么都没有，直接写return;这种写法适合函数返回类型是void的情况。
// return语句执⾏后，函数就彻底返回，后边的代码不再执⾏。
//void test()
//{
//	int n = 0;
//	scanf("%d", &n);
//	printf("hehe\n");
//	if (n = 5)
//		return;//返回为空，不会打印haha
//	printf("haha");
//}
//int main()
//{
//	test();
//		return 0;
//
//}
//---return返回的值和函数返回类型不⼀致，系统会⾃动将返回的值隐式转换为函数的返回类型
//int test()
//{
//	int n = 5;
//	if (n % 2 == 1)
//		return 3.5;//返回值为3，为int类型
//	else
//		return -3.5;
//
//}
//int main()
//{
//	int r = test();
//		printf("%d\n", r);
//}
//--- 如果函数中存在if等分⽀的语句，则要保证每种情况下都有return返回，否则会出现编译错误。
//int test()
//{
//	int n = 6;
//	if (n % 2 == 1)//n%2 !=1 时，没有返回值
//		return 1;//不是所有的控件路径都返回值
//}
//int main()
//{
//	int r = test();
//		printf("%d",r);
//	return 0;
//
//}
//-------------函数的返回类型如果不写，编译器会默认函数的返回类型是int。
//test()
//{
//	return 1;//没有定义test的返回值，返回类型为int型
//}
//int main()
//{
//	int r = test();
//	printf("%d\n", r);
//	return 0;
//}
//----------------------------- 函数写了返回类型，但是函数中没有使⽤return返回值，那么函数的返回值是未知的。
//int test()
//{
//	int n = 3 + 5;
//	printf("%d\n", n);
//
//}
//int main()
//{
//	int r = test();
//	printf("%d\n", r);//r=2,函数返回值为2
//	return 0;
//}
//数组做函数参数
//：写⼀个函数将⼀个整型数组的内容，全部置为 - 1，再写⼀个函数打印数组的内容。
//void set_arr(int arr[10], int sz)//形参
//{
//	int i = 0;
//	for (i = 0; i < sz; i++)
//	{
//		arr[i] = -1;
//	}
//}
//void print_arr(int arr[], int sz)
//{
//	int i = 0;
//	for (i = 0; i < sz; i++)
//	{
//		printf("%d", arr[i]);
//	}
//}
//int main()
//{
//	int arr[] = { 1,2,3,4,5,6,7,8,9 };
//	int sz = sizeof(arr) / sizeof(arr[1]);
//	set_arr(arr,sz);//数组传参
//	print_arr(arr, sz);
//	return 0;
//}
//----------- 嵌套调⽤
//假设我们计算某年某⽉有多少天？如果要函数实现，可以设计2个函数
//is_leap_year()：根据年份确定是否是闰年
//get_days_of_month()：调⽤is_leap_year确定是否是闰年后，再根据⽉计算这个⽉的天数
//int leap_year(int y)
//{
//	if (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0))
//				return 1;
//			else
//				return 0;
//}
//int day_of_month(int y, int m)
//{
//	int day[13] = { 0,31,29,31,30,31,30,31,31,30,31,30,31 }; 
//		int d = day[m];
//		//判断闰年
//		if (leap_year(y) && m == 2)
//		{
//			d += 1;
//		}
//		return d;
//}
//int main()
//{
//	int year = 0;
//	int month = 0;
//	scanf("%d %d", &year, &month);
//	int day = day_of_month(year, month);
//	printf("%d\n", day);
//	return 0;
//}
//------------------- 链式访问--所谓链式访问就是将⼀个函数的返回值作为另外⼀个函数的参数，像链条⼀样将函数串起来就是函数
//的链式访问。
//# include <string.h>
//int main()
//{
//	size_t len = strlen("acbde");
//	printf("%zd\n", len);
//	return 0;
//}
//int main()
//{
//	printf("%zd\n", strlen("abcde"));
// 	printf("%d ", printf("%d ", printf("%d ", 43)));最明显的例子
//	return 0;
//}
//-----------------------------------函数的声明和定义
// 函数的调⽤⼀定要满⾜，先声明后使⽤；
//函数的使用要保证：先声明后使用
////函数的声明是在说：
////函数的名字，参数，返回类型是什么
//----单个文件
//int is_leap_year(int y);//函数的声明
//int main()
//{
//	int y = 0;
//	scanf("%d", &y);
//	int r = is_leap_year(y);//函数的调用
//	if (r == 1)
//	{
//		printf("闰年\n");
//	}
//	else printf("非闰年\n");
//	return 0;
//}
//int is_leap_year(int y)//函数的定义
//{
//	if (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0))
//				return 1;
//			else
//				return 0;
//}
//也可以用这种方式写
//函数的定义 - 是一种特殊的声明
//int is_leap_year(int y)
//{
//	if (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0))
//		return 1;
//	else
//		return 0;
//}
//
//int main()
//{
//	int y = 0;
//	scanf("%d", &y);
//
//	if (is_leap_year(y)) //函数的调用
//		printf("闰年\n");
//	else
//		printf("不是闰年\n");
//
//	return 0;
//}
//------------多个⽂件
//⼀般情况下，函数的声明、类型的声明放在头⽂件（.h）中，函数的实现是放在源⽂件（.c）⽂件中。
//int main()
//{
//	int a = 10;
//	int b = 20;
//	int c = add(a, b);//函数的调用
//	printf("%d\n", c);
//	return 0;
//}
//static 和extern
//static是静态的的意思，可以⽤来：1.修饰局部变量   2.修饰全局变量    3.修饰函数
//extern是⽤来声明外部符号的。
//------------------------------extern 
// void test()
//{
//	int b = 100;
//	printf("1:b = %d\n", b);// 局部变量的作⽤域是变量所在的局部范围,出了这个范围无法使用
//}
//
//int main()
//{
//	printf("1:b = %d\n", b);//err
//	{
//		int a = 10;
//		printf("1: %d\n", a);
//	}
//	printf("2: %d\n", a);//err
//
//	return 0;
//}

//声明来自外部的符号
//extern int g_val;//// 全局变量---全局变量的作⽤域是整个⼯程（项⽬），跨文件也可以使用，需要extern声明外部符号
// void test()
//{
//	printf("2: g_val = %d\n", g_val);//ok
//}
//
//int main()
//{
//	printf("1: g_val = %d\n", g_val);//ok
//	test();
//	return 0;
//}
// 
//------------static修饰局部变量
//void test()
//{
//	int n = 1;
//	n++;
//	printf("%d\n", n);//正常情况下打印5个2
//}
//int main()
//{
//	int n = 0;
//	for (n = 0; n < 5; n++)
//	{
//		test();
//	}
//	return 0;
//}
//加入static
//void test()
//{
//	static int i = 1;
//	i++;
//	printf("%d\n", i);//打印2，3，4，5，6  
//	//static 修改了局部变量的声明周期，由栈区修改到了静态区，生命周期和全局变量一样，只有程序结束，变量才销毁
//}
//int main()
//{
//	int n = 0;
//	//printf("%d\n", i);i尽管生命周期变长了。但是它仍然是局部变量，只能在自己的局部范围内使用
//	for (n = 0; n < 5; n++)
//	{
//		test();
//	}
//	return 0;
//}
//--------------------- static 修饰全局变量
//extern int g_val;//声明来自外部符号
// //全局变量默认是代码外部链接属性, 在其他的.c文件中适当的声明是可以直接使用的
////但是被static修饰后
////这种外部链接属性就变成了内部链接属性,这个变量只能在自己所在的.c文件内部使用
////其他.c文件无法使用
//int main()
//{
//	printf("%d\n", g_val);
//	return 0;
//}
// ------------ static 修饰函数
//声明来自外部的函数
//extern void test();
//int main()
//{
//	//printf("%d\n", g_val);
//	test();
//	return 0;
//}
//函数也是默认就具有外部链接属性
//只要适当的声明，就可以在其他的.c文件中使用
//但是函数被static修饰后，这个函数的外部链接属性就变成了
//内部链接属性，也就是说这个函数只能在自己所在的.c文件内使用
//完！！！！